package org.wangchaocheng.cloudgallery.user.executor.command;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.wangchaocheng.cloudgallery.common.annotation.CommandExecutor;
import org.wangchaocheng.cloudgallery.common.exception.ErrorEnum;
import org.wangchaocheng.cloudgallery.common.exception.ExceptionFactory;
import org.wangchaocheng.cloudgallery.commond.user.UserRegisterCmd;
import org.wangchaocheng.cloudgallery.dto.user.UserAuthenticationDTO;
import org.wangchaocheng.cloudgallery.dto.user.UserDTO;
import org.wangchaocheng.cloudgallery.enums.user.UserAuthTypeEnum;
import org.wangchaocheng.cloudgallery.user.assembler.UserAssembler;
import org.wangchaocheng.cloudgallery.user.gateway.UserAuthenticationGateway;
import org.wangchaocheng.cloudgallery.user.gateway.UserGateway;

/**
 * 用户注册执行器
 * @author wangchaocheng
 * @date 2025-03-14
 **/
@CommandExecutor
@RequiredArgsConstructor
public class UserRegisterCmdExe {

    private final UserGateway userGateway;

    private final UserPasswordChangeCmdExe userPasswordChangeCmdExe;

    private final UserAuthenticationGateway userAuthenticationGateway;

    /**
     * 执行用户注册
     * @param cmd 用户注册命令
     */
    @Transactional(rollbackFor = Exception.class)
    public void execute(UserRegisterCmd cmd) {
        checkDuplicate(cmd);
        // 1. 组装用户信息
        UserDTO userDTO = UserAssembler.INSTANCE.assembleDTO(cmd);
        // 2. 保存用户信息
        userGateway.create(userDTO);
        // 3. 保存用户认证信息
        saveAuthentication(cmd);
    }

    /**
     * 检查用户注册时相关数据的唯一冲突
     * @param cmd 用户注册命令
     */
    private void checkDuplicate(UserRegisterCmd cmd) {
        // 1. 检查用户名是否存在
        if (userGateway.existByColumn(UserDTO::getUsername, cmd.getUsername())) {
            throw ExceptionFactory.bizException(ErrorEnum.E_BIZ_KEY_DUPLICATE, "注册失败，用户名已存在");
        }
        // 2. 校验邮箱
        if (StringUtils.isNotBlank(cmd.getEmail())){
            if (userGateway.existByColumn(UserDTO::getEmail, cmd.getEmail())) {
                throw ExceptionFactory.bizException(ErrorEnum.E_BIZ_KEY_DUPLICATE, "注册失败，邮箱已存在");
            }
        }
        // 3. 校验手机号
        if (StringUtils.isNotBlank(cmd.getPhoneNumber())){
            if (userGateway.existByColumn(UserDTO::getPhoneNumber, cmd.getPhoneNumber())) {
                throw ExceptionFactory.bizException(ErrorEnum.E_BIZ_KEY_DUPLICATE, "注册失败，手机号已存在");
            }
        }
    }

    private void saveAuthentication(UserRegisterCmd cmd) {
        String encodedPassword = userPasswordChangeCmdExe.encodePassword(cmd.getPassword());
        UserDTO user = userGateway.findByColumn(UserDTO::getUsername, cmd.getUsername());
        // 1. 保存用户名类型认证信息
        UserAuthenticationDTO userAuthenticationDTO = new UserAuthenticationDTO();
        userAuthenticationDTO.setUserId(user.getId());
        userAuthenticationDTO.setType(UserAuthTypeEnum.USERNAME.name());
        userAuthenticationDTO.setIdentifier(cmd.getUsername());
        userAuthenticationDTO.setCredential(encodedPassword);
        userAuthenticationGateway.save(userAuthenticationDTO);
        // 2. 保存手机号类型认证信息
        if (StringUtils.isNotBlank(cmd.getPhoneNumber())) {
            userAuthenticationDTO.setType(UserAuthTypeEnum.PHONE_NUMBER.name());
            userAuthenticationDTO.setIdentifier(cmd.getPhoneNumber());
            userAuthenticationDTO.setCredential(encodedPassword);
            userAuthenticationGateway.save(userAuthenticationDTO);
        }
        // 3. 保存邮箱类型认证信息
        if (StringUtils.isNotBlank(cmd.getEmail())) {
            userAuthenticationDTO.setType(UserAuthTypeEnum.EMAIL.name());
            userAuthenticationDTO.setIdentifier(cmd.getEmail());
            userAuthenticationDTO.setCredential(encodedPassword);
            userAuthenticationGateway.save(userAuthenticationDTO);
        }
    }


}
